﻿using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using SpCop.Core.Model;
using SpCop.Model;

namespace SpCop
{
    public abstract class ElementRuleBase : RuleBase
    {
        private readonly Predicate<Element> _elementFilter;

        protected ElementRuleBase() : this(a => true)
        {
        }

        protected ElementRuleBase(Predicate<Element> elementFilter)
        {
            Contract.Requires(elementFilter != null);

            _elementFilter = elementFilter;
        }

        public override void Visit(Feature item)
        {
            Contract.Requires(item != null && item.Elements != null && item.Elements.Length > 0);

            VisitCollection(item.Elements.Where(a => _elementFilter(a)), Visit);
        }

        public override IList<Problem> Check(Package package)
        {
            Contract.Requires(package != null);

            var problems = base.Check(package);
            VisitCollection(Package.Features, Visit);
            return problems;
        }

        public override void Visit(Element item)
        {
            Contract.Requires(item != null);
            Contract.Requires(item.Xml != null);
            Contract.Requires(item.Feature != null);
            
            VisitElement(Package, item.Feature, item);
        }

        protected abstract void VisitElement(Package package, Feature feature, Element item);
    }
}